package we3d.layer 
{
	import flash.display.Sprite;
	import flash.display.BitmapData;
	import flash.display.Bitmap;
	import flash.display.Graphics;
	
	import we3d.mesh.Face;
	import we3d.View3d;
	
	/**
	* A Layer is used for 2d output. Every Layer have a Sprite and optional a Bitmap. 
	* By default the containers of the layer are created and attached to the root target of the View <br/><br/>
	* 
	* Multiple layers in a View can be sorted by the polygons the Layer contains <br/><br/>
	* 
	* A Layer can be added to one View only
	*/
	public class Layer 
	{
		public function Layer (allowBitmap:Boolean=false) {
			useBitmap = allowBitmap;
		}
		
		/**
		* The width of the Layer, read only
		*/
		public var width:Number=0;
		/**
		* The height of the Layer, read only
		*/
		public var height:Number=0;
		/**
		* The main container of the layer. It contains a sprite for native polygons and optional a bitmap if useBitmap is true
		*/
		public var target:Sprite;
		/**
		* The Bitmap contains rendered polygons from all Scanline Rasterizers.
		*/
		public var bmpContainer:Bitmap=null;
		/**
		* The BitmapData of the Bitmap
		*/
		public var bmp:BitmapData;
		/**
		* If backToFront is true, the polygons are sorted from back to front, otherwise the reverse order from front to back.
		*/
		public var backToFront:Boolean=true;
		/**
		* If swapDepth is true, the Layer is sorted with other Layers in the view
		*/
		public var swapDepth:Boolean=true;
		/**
		* To use a background in the layer assign a Backdrop instance
		*/
		public var backdrop:Backdrop;
		/**
		* If graphics2Bitmap is true, all vector graphics from native rasterizer will be copied over the scanline polygons in the bitmap of the layer. This will free all vector graphics from memory after rendering
		*/
		public var graphics2Bitmap:Boolean=false;
		/**
		* If autoClear is true, the graphics in the layer will be cleared before every render
		*/
		public var autoClear:Boolean=true;
		/**
		 * If autoResize is true, the layer is resized when the size of the view changes
		 */
		public var autoResize:Boolean=true;
		/**
		* @private
		*/
		public var totalAvg:Number=0;
		/**
		* @private
		*/
		public var polys:Array=[];
		/**
		* @private
		*/
		public var _container:Sprite;
		/**
		* @private
		*/
		public var _graphics:Graphics;
		/**
		* @private
		*/
		public var cd:Number=0;
		/**
		* @private
		*/
		public var ch:Number=0;	
		/**
		* @private
		*/
		public var cl:Number=0;	
		/**
		* @private
		*/
		public var cp:Number=0;
		/**
		* @private
		*/
		public var pCount:int;
		private var useBitmap:Boolean=false;
		
		/**
		* Returns the graphics container of this Layer
		*/
		public function get container () :Sprite {
			return _container;
		}
		public function set container (mc:Sprite) :void {
			_container = mc;
			_graphics = mc.graphics;
		}
		
		/**
		* @private
		* Called by a view when the layer is added to the view
		* @param	view
		* @param	rootTarget	background, foreground or sorted target
		*/
		public function initialize (view:View3d, rootTarget:Sprite) :void {
			
			if(target == null) {
				target = new Sprite();
				rootTarget.addChild(target);
			}
			
			if(useBitmap) {
				
				if(bmpContainer == null) {
					bmpContainer = new Bitmap(null);
					target.addChild(bmpContainer);
				}
				
				if(width == 0) width = view.width;
				if(height == 0) height = view.height;
				
				createBitmapData();
			}
			
			if(!_container) {
				container = new Sprite();
				target.addChild(_container);
			}
		}
		
		/**
		* @private
		* Called by a view when the layer is removed from the view
		* @param	view
		* @param	rootTarget	background, foreground or sorted target
		*/
		public function remove (view:View3d, rootTarget:Sprite) :void {
			rootTarget.removeChild(target);
			bmpContainer = null;
			_container = null;
			target = null;
		}
		
		/**
		* @private
		*/
		public function createBitmapData () :void {
			if(bmp) bmp.dispose();
			
			if(width != 0 && height != 0) {
				bmp = new BitmapData(width, height, true, 0);
				bmpContainer.bitmapData = bmp;
			}
		}
		
		/**
		* @private
		*/
		public function initFrame (view:View3d) :void {
			
			polys.splice(0);
			pCount = 0;
			
			if(useBitmap) bmp.lock();
			
			if(backdrop) {
				if(useBitmap) {
					backdrop.drawToBitmap(view, this);
				}
				else backdrop.drawToSprite(view, this);
			}
		}
		
		/**
		* @private
		* Draw and sort the list of polygons
		* @param	view
		*/
		public function endFrame (view:View3d) :void {
			
			var L:int = polys.length;
			
			if(L>0) {
				
				if(backToFront) polys.sortOn("z", Array.NUMERIC);
				else polys.sortOn("z", Array.NUMERIC | Array.DESCENDING);
				
				view.currentLayer = this;
				
				var p:Face;
				var i:int;
				
				if(swapDepth) {
					var t:Number = 0;
					for(i=0; i<L; i++) {
						p = polys[i];
						t -= p.z;
						p.surface.rasterizer.draw(p.surface, view, p);
					}
					totalAvg = t/L;
				}else{
					for(i=0; i<L; i++) {
						p = polys[i];
						p.surface.rasterizer.draw(p.surface, view, p);
					}
				}
			}
			
			if(graphics2Bitmap) {
				bmp.draw( _container );
				_graphics.clear();
			}
			
			if(useBitmap) bmp.unlock();
		}
		
		/**
		* Called when the view clears the last render, view.autoClear and layer.autoClear have to be true
		*/
		public function clear (view:View3d) :void {
			_graphics.clear();
			if(useBitmap) bmp.fillRect(bmp.rect, 0);
		}
		
		/**
		* Resize the Layer
		* @param	w	width in pixels
		* @param	h	height in pixels
		*/
		public function setSize (w:int, h:int) :void {
			width = w;
			height = h;
			if(useBitmap && bmpContainer) createBitmapData();
		}
	
	}
}